/* Copyright 2009 Hauke Rehfeld This file is part of QuakeInjector. QuakeInjector is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. QuakeInjector is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with QuakeInjector. If not, see <http://www.gnu.org/licenses/>. */ package de.haukerehfeld.quakeinjector; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import de.haukerehfeld.quakeinjector.Package.Rating; public class PackageDatabaseParser implements java.io.Serializable { private final static Rating[] ratingTable = { Rating.Unrated, Rating.Crap, Rating.Poor, Rating.Average, Rating.Nice, Rating.Excellent }; /** * Parse the complete document */ public List<Requirement> parse(Document document) throws IOException, org.xml.sax.SAXException { HashMap<String, Requirement> packages = new HashMap<String,Requirement>(); Map<Package,List<String>> unresolvedRequirements = new HashMap<Package,List<String>>(); Element files = document.getDocumentElement(); for (Node file: XmlUtils.iterate(files.getChildNodes())) { if (XmlUtils.isElement(file)) { Package currentPackage = parsePackage((Element) file, unresolvedRequirements); packages.put(currentPackage.getId(), currentPackage); } /** @todo 2009-03-29 01:36 hrehfeld find out why this happens */ else { // System.out.println("node: " + file.getNodeName()); // System.out.println("Whoops, i thought file is an element!"); } } resolveRequirements(unresolvedRequirements, packages); List<Requirement> packageList = new ArrayList<Requirement>(packages.values()); return packageList; } private void resolveRequirements(Map<Package,List<String>> unresolvedRequirements, Map<String, Requirement> packages) { for (Map.Entry<Package,List<String>> entry: unresolvedRequirements.entrySet()) { Package current = entry.getKey(); List<String> reqs = entry.getValue(); // if (reqs.size() > 1) { // System.out.println(current.getId() + " has more than one requirement"); // } List<Requirement> resolvedRequirements = new ArrayList<Requirement>(reqs.size()); for (String id: reqs) { Requirement resolved = packages.get(id); if (resolved == null) { resolved = new UnavailableRequirement(id); packages.put(id, resolved); } resolvedRequirements.add(resolved); } current.setRequirements(resolvedRequirements); } } /** * Parse a single Package/file entry */ private Package parsePackage(Element file, Map<Package,List<String>> reqResolve) { String id = file.getAttribute("id"); Rating rating; { String ratingString = file.getAttribute("rating"); int ratingNumber = 0; if (!ratingString.equals("")) { try { ratingNumber = Integer.parseInt(ratingString); if (ratingNumber < 0 || ratingNumber > 5) { System.out.println("Rating of " + id + " is broken"); ratingNumber = 0; } } catch (java.lang.NumberFormatException e) { System.out.println("Rating of " + id + " is broken"); } } rating = ratingTable[ratingNumber]; } String title = XmlUtils.getFirstElement(file, "title").getTextContent().trim(); String author = XmlUtils.getFirstElement(file, "author").getTextContent().trim(); int size; try { size = Integer.parseInt(XmlUtils.getFirstElement(file, "size").getTextContent().trim()); } catch (java.lang.NumberFormatException e) { System.out.println("XML Parsing Error: malformed <size> tag on record \"" + id + "\""); size = 0; } String date = XmlUtils.getFirstElement(file, "date").getTextContent().trim(); String description = XmlUtils.getTextForNode(XmlUtils.getFirstElement(file, "description")) .trim(); String relativeBaseDir = null; String cmdline = null; ArrayList<String> startmaps = new ArrayList<String>(); ArrayList<String> requirements = new ArrayList<String>(); // parse techinfo stuff Element techinfo = XmlUtils.getFirstElement(file, "techinfo"); if (techinfo != null) { for (Node node: XmlUtils.iterate(techinfo.getChildNodes())) { if (!XmlUtils.isElement(node)) { continue; } Element info = (Element) node; if (info.getTagName().equals("zipbasedir")) { relativeBaseDir = info.getTextContent(); } else if (info.getTagName().equals("commandline")) { cmdline = info.getTextContent(); } else if (info.getTagName().equals("startmap")) { startmaps.add(info.getTextContent()); } else if (info.getTagName().equals("requirements")) { for (Node reqFile: XmlUtils.iterate(info.getChildNodes())) { if (XmlUtils.isElement(reqFile)) { String r = ((Element) reqFile).getAttribute("id"); requirements.add(r); } } } } } // System.out.println("id: " + id // + ", title: " + title // + ", size: " + size); //if there's no startmap tag, use the id if (startmaps.isEmpty()) { startmaps.add(id); } Package result = new Package(id, author, title, size, PackageDatabaseParser.parseDate(date), false, rating, description, relativeBaseDir, cmdline, startmaps, null); reqResolve.put(result, requirements); return result; } /** * Parses the date that's in dd.mm.yy format */ public static Date parseDate(String date) { String[] components = date.split("\\."); if (components.length < 3) { throw new RuntimeException("Xml Parsing error: date malformed"); } int day = Integer.parseInt(components[0]); int month = Integer.parseInt(components[1]) - 1; int year = Integer.parseInt(components[2]); if (year < 60) { year += 2000; } else { year += 1900; } return new GregorianCalendar(year, month, day).getTime(); } }